﻿using System;
using UnityEngine;

namespace winS.Unity.Rendering
{
    /// <summary>
    /// 表示屏幕
    /// </summary>
    public class Screen
    {
        /// <summary>
        /// 分辨率改变事件
        /// </summary>
        public event Action<Vector2Int> onResolutionChanged { add { AddResolutionChangedEvent(value); } remove { RemoveResolutionChangedEvent(value); } }

        /// <summary>
        /// 屏幕宽度
        /// </summary>
        public int width => UnityEngine.Screen.width;
        /// <summary>
        /// 屏幕高度
        /// </summary>
        public int height => UnityEngine.Screen.height;

        /// <summary>
        /// 渲染区域宽度
        /// </summary>
        public int renderWidth => (int)(UnityEngine.Screen.width * fixedAspectRenderer.widthRatio);
        /// <summary>
        /// 渲染区域高度
        /// </summary>
        public int renderHeight => (int)(UnityEngine.Screen.height * fixedAspectRenderer.heightRatio);

        /// <summary>
        /// 屏幕宽高比
        /// </summary>
        public float aspect => (float)width / height;
        /// <summary>
        /// 渲染区域宽高比
        /// </summary>
        public float renderAspect => (float)renderWidth / renderHeight;

        /// <summary>
        /// 是否启用了固定宽高比渲染
        /// </summary>
        public bool fixedAspectEnabled { get; private set; }

        /// <summary>
        /// 屏幕分辨率
        /// </summary>
        public Vector2Int resolution => new Vector2Int(width, height);
        /// <summary>
        /// 渲染区域分辨率
        /// </summary>
        public Vector2Int renderResolution => new Vector2Int(renderWidth, renderHeight);

        /// <summary>
        /// 固定宽高比渲染器
        /// </summary>
        private readonly FixedAspectRenderer fixedAspectRenderer = new FixedAspectRenderer();

        private Vector2Int lastResolution;

        private UpdateHandle updateHandle;
        private Action<Vector2Int> _onResolutionChanged;


        public void Refresh()
        {
            if (fixedAspectRenderer.enabled) fixedAspectRenderer.Update();
        }

        public void EnableFixedAspect(float aspect) => EnableFixedAspect(aspect, new DefaultFixedAspectRenderExecutor());

        /// <summary>
        /// 启用固定宽高比
        /// </summary>
        /// <param name="aspect">要启用的宽高比, 如16:9</param>
        /// <param name="fixedAspectRenderExecutor">要使用的渲染执行器</param>
        public void EnableFixedAspect(float aspect, IFixedAspectRenderExecutor fixedAspectRenderExecutor)
        {
            if (aspect <= 0f) throw new Exception($"{nameof(Screen)}.{nameof(EnableFixedAspect)}: 参数 {nameof(aspect)} 必须大于 0");
            fixedAspectEnabled = true;
            fixedAspectRenderer.Enable(aspect, fixedAspectRenderExecutor);
        }
        /// <summary>
        /// 禁用固定宽高比
        /// </summary>
        public void DisableFixedAspect()
        {
            fixedAspectEnabled = false;
            fixedAspectRenderer.Disable();
        }

        public Vector2 ScreenPointToRenderArea(Vector2 screenPoint)
        {
            if (fixedAspectRenderer.enabled)
            {
                int widthOffset = (int)((width - renderWidth) * 0.5f);
                int heightOffset = (int)((height - renderHeight) * 0.5f);
                return screenPoint - new Vector2(widthOffset, heightOffset);
            }
            return screenPoint;
        }

        private void AddResolutionChangedEvent(Action<Vector2Int> action)
        {
            _onResolutionChanged += action;
            updateHandle ??= Updater.AddUpdate(() =>
            {
                if (resolution == lastResolution) return;
                lastResolution = resolution;
                _onResolutionChanged?.Invoke(lastResolution);
            });
        }
        private void RemoveResolutionChangedEvent(Action<Vector2Int> action)
        {
            _onResolutionChanged -= action;
            if (updateHandle != null && _onResolutionChanged.GetInvocationList().Length == 0)
            {
                updateHandle.Stop();
                updateHandle = null;
            }
        }
    }
}